home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / shells / scsh-0.4 / scsh-0 / scsh-0.4.2 / scsh / network1.c < prev    next >
C/C++ Source or Header  |  1995-11-01  |  15KB  |  610 lines

  1. /* 
  2.  * Scheme48/scsh network interface.
  3.  * Routines that require custom C support.
  4.  * Copyright (c) 1994 by Brian D. Carlstrom
  5.  * Copyright (c) 1994 by Olin Shivers
  6.  */
  7.  
  8. #include "cstuff.h"
  9. #include <sys/types.h>
  10. #include <sys/time.h>
  11. #include <sys/socket.h>
  12. #include <sys/un.h>
  13. #include <errno.h>
  14. #include <netdb.h>
  15. #include <netinet/in.h>
  16. #include <arpa/inet.h>
  17. #include <string.h>
  18. #include <stdio.h>
  19.  
  20. /* Make sure our exports match up w/the implementation: */
  21. #include "network1.h"
  22.  
  23. extern int h_errno;
  24.  
  25. /* to extract a 4 byte long value from a scheme string */
  26.  
  27. #define GET_LONG(x,n) (*((u_long *)(ADDRESS_AFTER_HEADER((x),unsigned char)+(n*4))))
  28.  
  29. #define SET_LONG(x,n,v) GET_LONG((x),(n))=(u_long)(v);
  30.  
  31. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  32. int scheme_bind(int sockfd, int family, scheme_value scheme_name)
  33. {
  34.   switch(family)
  35.     {
  36.     case AF_UNIX: 
  37.       {
  38.     struct sockaddr_un name;
  39.     int scheme_length=STRING_LENGTH(scheme_name);
  40.     
  41.     name.sun_family=AF_UNIX;    
  42.     if (scheme_length>=(108-1)) /* save space for \0 */
  43.       return(-1);
  44.     strncpy(name.sun_path,
  45.         ADDRESS_AFTER_HEADER(scheme_name,char),
  46.         scheme_length);    /* copy to c string */
  47.     name.sun_path[scheme_length+1]='\0'; /* add null */
  48.     return(bind(sockfd,(struct sockaddr *)&name,sizeof(name)));
  49.     break;
  50.       }
  51.     case AF_INET: 
  52.       {
  53.     struct sockaddr_in name;
  54.  
  55.     u_long  addr=GET_LONG(scheme_name,0);
  56.     u_short port=htons((u_short)ntohl(GET_LONG(scheme_name,1)));
  57.     name.sin_family=AF_INET;
  58.     name.sin_addr.s_addr=addr;
  59.     name.sin_port=port;
  60.     return(bind(sockfd,(struct sockaddr *)&name,sizeof(name)));
  61.     break;
  62.       }
  63.     default:
  64.       return(-1);        /* error unknown address family */
  65.     }
  66. }
  67.  
  68. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  69. int scheme_connect(int sockfd, int family, scheme_value scheme_name)
  70. {
  71.   switch(family)
  72.     {
  73.     case AF_UNIX: 
  74.       {
  75.     struct sockaddr_un name;
  76.     int scheme_length=STRING_LENGTH(scheme_name);
  77.     
  78.     name.sun_family=AF_UNIX;    
  79.     if (scheme_length>=(108-1)) /* save space for \0 */
  80.       return(-1);
  81.     strncpy(name.sun_path,
  82.         ADDRESS_AFTER_HEADER(scheme_name,char),
  83.         scheme_length);    /* copy to c string */
  84.     name.sun_path[scheme_length+1]='\0'; /* add null */
  85.     return(connect(sockfd,(struct sockaddr *)&name,sizeof(name)));
  86.     break;
  87.       }
  88.     case AF_INET: 
  89.       {
  90.     struct sockaddr_in name;
  91.     
  92.     u_long addr=GET_LONG(scheme_name,0);
  93.     u_short port=htons((u_short)ntohl(GET_LONG(scheme_name,1)));
  94.  
  95.     name.sin_family=AF_INET;
  96.     name.sin_addr.s_addr=addr;
  97.     name.sin_port=port;
  98.  
  99.     return(connect(sockfd,(struct sockaddr *)&name,sizeof(name)));
  100.  
  101.     break;
  102.       }
  103.     default: 
  104.       return(-1);
  105.       /* error unknown address family */ 
  106.     } 
  107. }
  108.  
  109. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  110. int scheme_accept(int sockfd, int family, scheme_value scheme_name)
  111. {
  112.   switch(family)
  113.     {
  114.     case AF_UNIX: 
  115.       {
  116.     struct sockaddr_un name;
  117.     int namelen=sizeof(name);
  118.     int newsockfd=accept(sockfd,(struct sockaddr *)&name,&namelen);
  119.  
  120.     if (newsockfd < 0)
  121.       return(-1);
  122.  
  123.     return(newsockfd);
  124.     break;
  125.       }
  126.     case AF_INET: 
  127.       {
  128.     struct sockaddr_in name;
  129.     int namelen=sizeof(name);
  130.     int newsockfd=accept(sockfd,(struct sockaddr *)&name,&namelen);
  131.     
  132.     if (newsockfd < 0)
  133.       return(-1);
  134.     SET_LONG(scheme_name,0,name.sin_addr.s_addr);
  135.     SET_LONG(scheme_name,1,htonl((u_long)ntohs(name.sin_port)));
  136.     return(newsockfd);
  137.     break;
  138.       }
  139.     default:
  140.       return(-1);        /* error unknown address family */
  141.     }
  142. }
  143.  
  144. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  145. int scheme_peer_name(int sockfd, int family, scheme_value scheme_name)
  146. {
  147.   switch(family)
  148.     {
  149.     case AF_INET: 
  150.       {
  151.     struct sockaddr_in name;
  152.     int namelen=sizeof(name);
  153.     int value=getpeername(sockfd,(struct sockaddr *)&name,&namelen);
  154.     
  155.     if (value < 0)
  156.       return(-1);
  157.     SET_LONG(scheme_name,0,name.sin_addr.s_addr);
  158.     SET_LONG(scheme_name,1,htonl((u_long)ntohs(name.sin_port)));
  159.     return(value);
  160.     break;
  161.       }
  162.     default:
  163.       return(-1);        /* error unknown address family */
  164.     }
  165. }
  166.  
  167. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  168. int scheme_socket_name(int sockfd, int family, scheme_value scheme_name)
  169. {
  170.   switch(family)
  171.     {
  172.     case AF_INET: 
  173.       {
  174.     struct sockaddr_in name;
  175.     int namelen=sizeof(name);
  176.     int value=getsockname(sockfd,(struct sockaddr *)&name,&namelen);
  177.     
  178.     if (value < 0)
  179.       return(-1);
  180.     SET_LONG(scheme_name,0,name.sin_addr.s_addr);
  181.     SET_LONG(scheme_name,1,htonl((u_long)ntohs(name.sin_port)));
  182.     return(value);
  183.     break;
  184.       }
  185.     default:
  186.       return(-1);        /* error unknown address family */
  187.     }
  188. }
  189.  
  190. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  191. int scheme_socket_pair(int type, int *s1, int *s2)
  192. {
  193.   int sv[2];
  194.   if( socketpair(PF_UNIX,type,0,sv) ) {
  195.     *s1 = 0; *s2 = 0;
  196.     return errno;
  197.   }
  198.   *s1 = sv[0]; *s2 = sv[1];
  199.   return 0;
  200. }
  201.  
  202. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  203. int recv_substring(int s,
  204.            int flags,
  205.            scheme_value buf, 
  206.            int start, 
  207.            int end, 
  208.            scheme_value scheme_name)
  209. {
  210.  
  211.   switch(STRING_LENGTH(scheme_name))
  212.     {
  213. #ifdef NOTUSED
  214. /* no longer used. always return remote socket info */
  215.     case 0:            /* only with connected sockets */
  216.       {
  217.     return recv(s, StrByte(buf,start), end-start, flags);
  218.       }
  219. #endif
  220.     case 8:            /* AF_INET */
  221.       {
  222.     struct sockaddr_in name;
  223.     int namelen=sizeof(name);
  224.     int cc=recvfrom(s, 
  225.             StrByte(buf,start), end-start, 
  226.             flags,
  227.             (struct sockaddr *)&name, &namelen);
  228.     
  229.     if (cc < 0)
  230.       return(-1);
  231.     SET_LONG(scheme_name,0,name.sin_addr.s_addr);
  232.     SET_LONG(scheme_name,1,htonl((u_long)ntohs(name.sin_port)));
  233.     return(cc);
  234.     break;
  235.       }
  236.     default:
  237.       return(-1);        /* error unknown address family */
  238.     }
  239. }
  240.       
  241. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  242. int send_substring(int s,
  243.            int flags,
  244.            scheme_value buf, 
  245.            int start, 
  246.            int end, 
  247.            int family, 
  248.            scheme_value scheme_name)
  249. {
  250.  
  251.   switch(family)
  252.     {
  253.     case 0:            /* only with connected sockets */
  254.       {
  255.     return send(s, StrByte(buf,start), end-start, flags);
  256.       }
  257.     case AF_UNIX:
  258.       {
  259.     struct sockaddr_un name;
  260.     int scheme_length=STRING_LENGTH(scheme_name);
  261.     
  262.     name.sun_family=AF_UNIX;    
  263.     if (scheme_length>=(108-1)) /* save space for \0 */
  264.       return(-1);
  265.     strncpy(name.sun_path,
  266.         ADDRESS_AFTER_HEADER(scheme_name,char),
  267.         scheme_length);    /* copy to c string */
  268.     name.sun_path[scheme_length+1]='\0'; /* add null */
  269.     return(sendto(s, 
  270.               StrByte(buf,start), end-start, 
  271.               flags,
  272.               (struct sockaddr *)&name, sizeof(name)));
  273.     break;
  274.       }
  275.     case AF_INET:
  276.       {
  277.     struct sockaddr_in name;
  278.     u_long  addr=GET_LONG(scheme_name,0);
  279.     u_short port=htons((u_short)ntohl(GET_LONG(scheme_name,1)));
  280.     name.sin_family=AF_INET;
  281.     name.sin_addr.s_addr=addr;
  282.     name.sin_port=port;
  283.  
  284.     return(sendto(s, 
  285.               StrByte(buf,start), end-start, 
  286.               flags,
  287.               (struct sockaddr *)&name, sizeof(name)));
  288.     break;
  289.       }
  290.     default:
  291.       return(-1);        /* error unknown address family */
  292.     }
  293. }
  294.       
  295. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  296. int scheme_getsockopt (int s,
  297.                int level,
  298.                int optname)
  299. {
  300.   int optval;
  301.   int optlen=sizeof(optval);
  302.   
  303.   if (getsockopt(s,level,optname,(char *)&optval,&optlen) == -1)
  304.     return(-1);
  305.   return(optval);
  306.  
  307. }
  308.  
  309. int scheme_getsockopt_linger (int s,
  310.                   int level,
  311.                   int optname,
  312.                   int *out_time)
  313. {
  314.   struct linger optval;
  315.   int optlen=sizeof(optval);
  316.   
  317.   if (getsockopt(s,level,optname,(char *)&optval,&optlen) == -1)
  318.     return(-1);
  319.   *out_time=optval.l_linger;
  320.   return(optval.l_onoff);
  321. }
  322.  
  323. int scheme_getsockopt_timeout (int s,
  324.                    int level,
  325.                    int optname,
  326.                    int *out_usec)
  327. {
  328.   struct timeval optval;
  329.   int optlen=sizeof(optval);
  330.   
  331.   if (getsockopt(s,level,optname,(char *)&optval,&optlen) == -1)
  332.     return(-1);
  333.   *out_usec=optval.tv_usec;
  334.   return(optval.tv_sec);
  335. }
  336. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  337. int scheme_setsockopt (int s,
  338.                int level,
  339.                int optname,
  340.                int optval)
  341. {
  342.   return(setsockopt(s,level,optname,(char *)&optval,sizeof(optval)));
  343. }
  344.  
  345. int scheme_setsockopt_linger (int s,
  346.                   int level,
  347.                   int optname,
  348.                   int onoff,
  349.                   int linger)
  350. {
  351.   struct linger optval;
  352.  
  353.   optval.l_onoff=onoff;
  354.   optval.l_linger=linger;
  355.   
  356.   return(setsockopt(s,level,optname,(char *)&optval,sizeof(optval)));
  357. }
  358.  
  359. int scheme_setsockopt_timeout (int s,
  360.                    int level,
  361.                    int optname,
  362.                    int sec,
  363.                    int usec)
  364. {
  365.   struct timeval optval;
  366.   optval.tv_sec=sec;
  367.   optval.tv_usec=usec;
  368.   
  369.   return(setsockopt(s,level,optname,(char *)&optval,sizeof(optval)));
  370. }
  371.  
  372. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  373. /* Routines for looking up hosts                                           */
  374. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  375. int scheme_host_address2host_info(scheme_value scheme_name,
  376.                   char** hostname,
  377.                   char*** aliases,
  378.                   char*** addresses)
  379. {
  380.   struct in_addr name;
  381.   struct hostent *host;
  382.  
  383.   u_long  addr=GET_LONG(scheme_name,0);
  384.   name.s_addr=addr;
  385.  
  386.   host=gethostbyaddr((char *)&name,sizeof(name),AF_INET);
  387.   
  388.   if(host==NULL)
  389.     {
  390.       *hostname =NULL;
  391.       *aliases  =NULL;
  392.       *addresses=NULL;
  393.       return(h_errno);
  394.     }
  395.   
  396.   *hostname =host->h_name;
  397.   *aliases  =host->h_aliases;
  398.   *addresses=host->h_addr_list;
  399.   return(0);
  400. }
  401.  
  402. int scheme_host_name2host_info(const char* scheme_name,
  403.                    char**  hostname,
  404.                    char*** aliases,
  405.                    char*** addresses)
  406. {
  407.   struct in_addr name;
  408.   struct hostent *host;
  409.  
  410.   if ((name.s_addr=inet_addr(scheme_name)) != -1)
  411.     host=gethostbyaddr((char *)&name,sizeof(name),AF_INET);
  412.   else
  413.     host=gethostbyname(scheme_name);
  414.   
  415.   if(host==NULL)
  416.     {
  417.       *hostname =NULL;
  418.       *aliases  =NULL;
  419.       *addresses=NULL;
  420.       return(h_errno);
  421.     }
  422.   
  423.   *hostname =host->h_name;
  424.   *aliases  =host->h_aliases;
  425.   *addresses=host->h_addr_list;
  426.   return(0);
  427. }
  428.  
  429. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  430. /* Routines for looking up networks                                        */
  431. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  432. int scheme_net_address2net_info(scheme_value scheme_name,
  433.                 scheme_value scheme_net,
  434.                 char** netname,
  435.                 char*** aliases)
  436. {
  437.   struct netent *net;
  438.  
  439.   net=getnetbyaddr(ntohl(GET_LONG(scheme_name,0)),AF_INET);
  440.   
  441.   if(net==NULL)
  442.     {
  443.       *netname=NULL;
  444.       *aliases=NULL;
  445.       return(-1);
  446.     }
  447.   
  448.   *netname=net->n_name;
  449.   *aliases=net->n_aliases;
  450.   SET_LONG(scheme_net,0,net->n_net);
  451.   return(0);
  452. }
  453.  
  454. int scheme_net_name2net_info(const char*   scheme_name,
  455.                  scheme_value  scheme_net,
  456.                  char**  netname,
  457.                  char*** aliases)
  458. {
  459.   struct netent *net=getnetbyname(scheme_name);
  460.   
  461.   if(net==NULL)
  462.     {
  463.       *netname=NULL;
  464.       *aliases=NULL;
  465.       return(-1);
  466.     }
  467.   
  468.   *netname=net->n_name;
  469.   *aliases=net->n_aliases;
  470.   SET_LONG(scheme_net,0,net->n_net);    /* ??? -Olin */
  471.   return(0);
  472. }
  473.  
  474. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  475. /* Routines for looking up services                                        */
  476. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  477.  
  478. /* in_port should be declared u_short, but cig doesn't know about them. */
  479. int scheme_serv_port2serv_info(int in_port,
  480.                    const char* in_proto,
  481.                    char**      out_servname,
  482.                    char***     out_aliases,
  483.                    int*        out_port,
  484.                    char**      out_protocol)
  485. {
  486.   struct servent *serv;
  487.  
  488.   serv=getservbyport(in_port,in_proto);
  489.   
  490.   if(serv==NULL)
  491.     {
  492.       *out_servname=NULL;
  493.       *out_aliases=NULL;
  494.       *out_port=0;
  495.       *out_protocol=NULL;
  496.       return(-1);
  497.     }
  498.   
  499.   *out_servname=serv->s_name;
  500.   *out_aliases =serv->s_aliases;
  501.   *out_port    =(int)ntohs(serv->s_port);
  502.   *out_protocol=serv->s_proto;
  503.   return(0);
  504. }
  505.  
  506. int scheme_serv_name2serv_info(const char*    in_name,
  507.                    const char*    in_proto,
  508.                    char**   out_servname,
  509.                    char***  out_aliases,
  510.                    int*     out_port,
  511.                    char**   out_protocol)
  512. {
  513.   struct servent *serv=getservbyname(in_name,in_proto);
  514.   
  515.   if(serv==NULL)
  516.     {
  517.       *out_servname=NULL;
  518.       *out_aliases=NULL;
  519.       *out_port=0;
  520.       *out_protocol=NULL;
  521.       return(-1);
  522.     }
  523.   
  524.   *out_servname=serv->s_name;
  525.   *out_aliases =serv->s_aliases;
  526.   *out_port    =(int)ntohs(serv->s_port);
  527.   *out_protocol=serv->s_proto;
  528.   return(0);
  529. }
  530.  
  531. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  532. /* Routines for looking up protocols                                       */
  533. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  534. int scheme_proto_num2proto_info(int     in_proto,
  535.                 char**  out_protoname,
  536.                 char*** out_aliases,
  537.                 int*    out_protocol)
  538. {
  539.   struct protoent *proto;
  540.  
  541.   proto=getprotobynumber(in_proto);
  542.   
  543.   if(proto==NULL)
  544.     {
  545.       *out_protoname=NULL;
  546.       *out_aliases=NULL;
  547.       *out_protocol=0;
  548.       return(-1);
  549.     }
  550.   
  551.   *out_protoname=proto->p_name;
  552.   *out_aliases  =proto->p_aliases;
  553.   *out_protocol =proto->p_proto;
  554.   return(0);
  555. }
  556.  
  557. int scheme_proto_name2proto_info(const char* in_name,
  558.                  char**  out_protoname,
  559.                  char*** out_aliases,
  560.                  int*    out_protocol)
  561. {
  562.   struct protoent *proto=getprotobyname(in_name);
  563.   
  564.   if(proto==NULL)
  565.     {
  566.       *out_protoname=NULL;
  567.       *out_aliases=NULL;
  568.       *out_protocol=0;
  569.       return(-1);
  570.     }
  571.   
  572.   *out_protoname=proto->p_name;
  573.   *out_aliases  =proto->p_aliases;
  574.   *out_protocol =proto->p_proto;
  575.   return(0);
  576. }
  577.  
  578.  
  579. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  580. /* Low Level Junk                                                          */
  581. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  582. /* svec is a Scheme vector of C carriers. Scan over the C longs
  583. ** in cvec, and initialise the corresponding carriers in svec.
  584. */
  585. void set_longvec_carriers(scheme_value svec, long const * const * cvec)
  586. {
  587.   int svec_len = VECTOR_LENGTH(svec);
  588.   long const * const *cv = cvec;
  589.   scheme_value *sv = &VECTOR_REF(svec,0);
  590.  
  591.   for(; svec_len > 0; cv++, sv++, svec_len-- ) {
  592.     /* *sv is a (make-string 4) */
  593.     scheme_value carrier = *sv;
  594.     (*((u_long *)(ADDRESS_AFTER_HEADER(carrier,unsigned char))))
  595.       =(long)**cv;
  596.   }
  597. }
  598.  
  599. /*  One arg, a zero-terminated C word vec. Returns length.
  600. **  The terminating null is not counted. Returns #f on NULL.
  601. */
  602.  
  603. scheme_value veclen(const long *vec)
  604. {
  605.   const long *vptr = vec;
  606.   if( !vptr ) return SCHFALSE;
  607.   while( *vptr ) vptr++;
  608.   return ENTER_FIXNUM(vptr - vec);
  609. }
  610.